package autokeyboard.gui;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JToolBar.Separator;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import autokeyboard.data.GetData;
import autokeyboard.data.PicturePanel;
import autokeyboard.data.RobotType;
import autokeyboard.handler.AutoKeyboardEvent;
import autokeyboard.handler.PanelButtonEvent;
import autokeyboard.handler.ShowDialogEvent;

@SuppressWarnings("serial")
public class PanelButton extends JPanel
{
	private JToolBar			toolbar					= new JToolBar();

	private JButton				btNew					= new JButton();
	private JButton				btSave					= new JButton();
	private JButton				btOpen					= new JButton();

	private Separator			s1						= new Separator();

	private JButton				btStart					= new JButton();
	private JButton				btStop					= new JButton();
	private JButton				btImport				= new JButton();

	private Separator			s2						= new Separator();

	private JButton				btUp					= new JButton();
	private JButton				btDown					= new JButton();
	private JButton				btDelete				= new JButton();

	private Separator			s3						= new Separator();

	private JPanel				panelKeyStroke			= new JPanel();

	private Separator			s4						= new Separator();

	private JButton				btSetting				= new JButton();
	private JButton				btHelp					= new JButton();
	private JButton				btAbout					= new JButton();

	private JLabel				lblDelay				= new JLabel("Stroke delay");
	private JTextField			tfDelay					= new JTextField(6);
	private JButton				btSetDelay				= new JButton("set delay");

	private GetData				getPath					= new GetData();

	private JButton[]			listButton				= { btNew, btSave, btOpen, btStart, btStop, btImport, btUp, btDown, btDelete, btSetting, btHelp, btAbout };
	private PicturePanel[]		listPicPanel			= new PicturePanel[listButton.length];
	private String[]			listPath				= getPath.getListIconsNormal();
	private String[]			listPathOver			= getPath.getListIconsOver();
	private String[]			listPathDisabled		= getPath.getListIconsNormalDisabled();
	private String[]			listPathOverDisabled	= getPath.getListIconsOverDisabled();

	private ShowDialogEvent		showDlg					= new ShowDialogEvent();
	private AutoKeyboardEvent	autoEvent;
	private PanelButtonEvent	event					= new PanelButtonEvent();

	private JFrame				frame;

	private JTable				table;
	private ArrayList<Object[]>	listObject;
	private ListSelectionModel	listSelectionModel;

	private ArrayList<String[]>	listKeyAndDelay			= new ArrayList<String[]>();

	private RobotType			robot					= new RobotType();

	public PanelButton(JFrame frame)
	{
		this.frame = frame;
		autoEvent = new AutoKeyboardEvent(frame);
		initComponent();
	}

	private void initComponent()
	{
		for(int i = 0; i<listPicPanel.length; i++)
		{
			listPicPanel[i] = new PicturePanel();
		}
		setMainLayout();
		setLayoutPanelKeyStroke();

		setButtonProperties();
		setToolbarProperties();
		addItemToToolbar();

		keyEvent();
		buttonEvent();
		mouseEvent();
		focusEvent();
		stateListener();
	}

	public void setTable(JTable table)
	{
		this.table = table;
		event.setTable(this.table);
	}

	public void setListObject(ArrayList<Object[]> listObject)
	{
		this.listObject = listObject;
		event.setListObject(this.listObject);
	}

	public void setListSelectionModel(ListSelectionModel listSelectionModel)
	{
		this.listSelectionModel = listSelectionModel;
	}

	public JButton getBtUp()
	{
		return this.btUp;
	}

	public JButton getBtDown()
	{
		return this.btDown;
	}

	public JButton getBtDelete()
	{
		return this.btDelete;
	}

	public ArrayList<String[]> getListKeyAndDelay()
	{
		return this.listKeyAndDelay;
	}

	private void setMainLayout()
	{
		this.setLayout(new FlowLayout(FlowLayout.LEFT));
		this.add(toolbar);
	}

	/**
	 * This will set all properties for all button
	 */
	private void setButtonProperties()
	{
		int counter = 0;
		for (final JButton button : listButton)
		{
			button.setPreferredSize(new Dimension(50, 50));
			button.setFocusable(false);
			listPicPanel[counter] = new PicturePanel();
			listPicPanel[counter].path = listPathDisabled[counter];
			listPicPanel[counter].repaint();
			button.add(listPicPanel[counter]);
			counter++;
			// button.setIcon(new
			// ImageIcon(getClass().getResource(listPath[counter++])));
			// button.setIcon(new
			// ImageIcon(getClass().getResource(listPath[counter++])));
		}

		btNew.setToolTipText("New auto keyboard");
		btSave.setToolTipText("Save current file");
		btOpen.setToolTipText("Open a file");

		btStart.setToolTipText("Start auto keyboard");
		btStop.setToolTipText("Auto Mouse - Coming soon........");
		btStop.setEnabled(false);
		btImport.setToolTipText("Import your file to quick create auto type");

		btUp.setToolTipText("Move one line up");
		btDown.setToolTipText("Move one line down");
		btDelete.setToolTipText("Delete one line");

		btSetting.setToolTipText("Setting your own controls");
		btHelp.setToolTipText("View help");
		btAbout.setToolTipText("About");
	}

	/**
	 * This method will be add all button, separator and panel that need to be
	 * used
	 */
	private void addItemToToolbar()
	{
		toolbar.add(btNew);
		toolbar.add(btSave);
		toolbar.add(btOpen);

		toolbar.add(s1);

		toolbar.add(btStart);
		toolbar.add(btImport);
		toolbar.add(btStop);

		toolbar.add(s2);

		toolbar.add(btUp);
		toolbar.add(btDown);
		toolbar.add(btDelete);

		toolbar.add(s3);
		toolbar.add(btSetting);
		toolbar.add(btHelp);
		toolbar.add(btAbout);

		toolbar.add(s4);
		toolbar.add(panelKeyStroke);

	}

	/**
	 * This will set toolBar properties
	 */
	private void setToolbarProperties()
	{
		toolbar.setEnabled(false);
		toolbar.setBorderPainted(false);
		toolbar.setRollover(true);
		toolbar.setFloatable(false);
	}

	/**
	 * This method will add some components and set panel KeyStroke properties
	 */
	private void setLayoutPanelKeyStroke()
	{
		panelKeyStroke.setLayout(new FlowLayout());
		panelKeyStroke.setPreferredSize(new Dimension(160, 70));
		panelKeyStroke.add(lblDelay);
		panelKeyStroke.add(tfDelay);
		panelKeyStroke.add(btSetDelay);

		tfDelay.setText("50");
	}

	/**
	 * This method will check whether your input is number or not.
	 * 
	 * @param text
	 * @return
	 */
	private boolean isValidNumber(String text)
	{
		if (text.length() != 0)
		{
			char[] list = text.toCharArray();
			for (char item : list)
			{
				if (!Character.isDigit(item)) return false;
			}
		}
		return true;
	}

	/**
	 * This method will add keyEvent into textField
	 * <p>
	 * If your input is not a number. It will delete your letter
	 */
	private void keyEvent()
	{
		tfDelay.addKeyListener(new KeyAdapter()
		{
			@Override
			public void keyPressed(KeyEvent evt)
			{
				/**
				 * Check whether your input is a number. If it is not a number.
				 * It will delete your input
				 */
				if (!isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					tfDelay.setText(tfDelay.getText().substring(0, tfDelay.getText().length() - 1));
				}
			}

			@Override
			public void keyReleased(KeyEvent evt)
			{
				/**
				 * Check whether your input is a number. If it is not a number.
				 * It will delete your input
				 */
				if (!isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					tfDelay.setText(tfDelay.getText().substring(0, tfDelay.getText().length() - 1));
				}
				else if (isValidNumber(tfDelay.getText()) && tfDelay.getText().length() != 0)
				{
					try
					{
						int number = Integer.parseInt(tfDelay.getText());
						if (number < 1)
						{
							tfDelay.setText("1");
						}
					} catch (Exception ex)
					{
					}
				}
			}
		});
	}

	/**
	 * This method will addFocusListener for tfDelay
	 * <p>
	 * When tfDelay is lost focus it will check whether tfDelay had a value or
	 * not. Unless it had a value this will set the default value is 50 to that
	 * text field
	 */
	private void focusEvent()
	{
		tfDelay.addFocusListener(new FocusAdapter()
		{
			@Override
			public void focusLost(FocusEvent e)
			{
				if (tfDelay.getText().length() == 0)
				{
					tfDelay.setText("50");
				}
			}

			@Override
			public void focusGained(FocusEvent e)
			{
				tfDelay.setSelectionStart(0);
				tfDelay.setSelectionEnd(tfDelay.getText().length());
			}
		});
	}

	/**
	 * This method will add event to all your button
	 */
	private void buttonEvent()
	{
		btNew.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				autoEvent.menuItemNewEvent(table, listObject);
			}
		});

		btSave.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				autoEvent.menuItemSaveEvent(table, listObject);
			}
		});

		btOpen.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				autoEvent.menuItemOpenEvent(table, listObject);
			}
		});

		btStart.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				addKeyToList();
				showDlg.showStartOptionDialog(frame);

				// set hotKey for robot
				if (StartOptionDialog.isStartPressed)
				{
					robot.setStartKey(StartOptionDialog.listHostKey[0]);
					robot.setPauseKey(StartOptionDialog.listHostKey[1]);
					robot.setStopKey(StartOptionDialog.listHostKey[2]);
				}
			}
		});

		btStop.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{

			}
		});

		btImport.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				showDlg.showImportDialog(frame, table, listObject);
			}
		});

		btUp.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				int index = listSelectionModel.getMinSelectionIndex();
				event.moveUpOneLine(index, btDown, btUp);
			}
		});

		btDown.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				int index = listSelectionModel.getMinSelectionIndex();
				event.moveDownOneLine(index, btDown, btUp);
			}
		});

		btDelete.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				int index = listSelectionModel.getMinSelectionIndex();
				event.deleteOneRow(index, btDelete, btUp, btDown);
			}
		});

		btSetting.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				showDlg.showControlsDialog(frame);
			}
		});

		btHelp.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				showDlg.showHelpDialog(frame);
			}
		});

		btAbout.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				showDlg.showAboutWindow(frame);
			}
		});
		btSetDelay.addActionListener(new ActionListener()
		{

			@Override
			public void actionPerformed(ActionEvent e)
			{
				TablePanel.keyStrokeDelay = Integer.parseInt(tfDelay.getText());
			}
		});
	}

	/**
	 * This method will set mouse event for all button
	 */
	private void mouseEvent()
	{
		for (final JButton button : listButton)
		{
			button.addMouseListener(new MouseAdapter()
			{
				@Override
				public void mousePressed(MouseEvent evt)
				{
					int index = indexOfButton(button);
					if(button.isEnabled())
					{
						listPicPanel[index].path = listPathOver[index];
						listPicPanel[index].repaint();
					}else if(!button.isEnabled())
					{
						listPicPanel[index].path = listPathOverDisabled[index];
						listPicPanel[index].repaint();
					}
				}
				@Override
				public void mouseReleased(MouseEvent evt)
				{
					int index = indexOfButton(button);
					if(button.isEnabled())
					{
						listPicPanel[index].path = listPathOver[index];
						listPicPanel[index].repaint();
					}else if(!button.isEnabled())
					{
						listPicPanel[index].path = listPathOverDisabled[index];
						listPicPanel[index].repaint();
					}
				}
				@Override
				public void mouseEntered(MouseEvent evt)
				{
					int index = indexOfButton(button);
					if(button.isEnabled())
					{
						listPicPanel[index].path = listPathOver[index];
						listPicPanel[index].repaint();
					}else if(!button.isEnabled())
					{
						listPicPanel[index].path = listPathOverDisabled[index];
						listPicPanel[index].repaint();
					}

					// button.setIcon(new
					// ImageIcon(getClass().getResource(listPathOver[indexOfButton(button)])));
				}

				@Override
				public void mouseExited(MouseEvent evt)
				{
					int index = indexOfButton(button);
					if(button.isEnabled())
					{
						listPicPanel[index].path = listPath[index];
						listPicPanel[index].repaint();
					}else if(!button.isEnabled())
					{
						listPicPanel[index].path = listPathDisabled[index];
						listPicPanel[index].repaint();
					}
					// button.setIcon(new
					// ImageIcon(getClass().getResource(listPath[indexOfButton(button)])));
				}
			});
		}
	}

	private void stateListener()
	{
		for (final JButton button : listButton)
		{
			button.addChangeListener(new ChangeListener()
			{

				@Override
				public void stateChanged(ChangeEvent e)
				{
					if (!button.isEnabled())
					{
						int index = indexOfButton(button);
						listPicPanel[index].path = listPathDisabled[index];
						listPicPanel[index].repaint();
						listPicPanel[index].setEnabled(false);
					}
					else if (button.isEnabled())
					{
						int index = indexOfButton(button);
						listPicPanel[index].path = listPath[index];
						listPicPanel[index].repaint();
						listPicPanel[index].setEnabled(true);
					}
				}
			});
		}
	}

	/**
	 * This method will return index of your input button
	 * 
	 * @param button
	 * @return index of your input button
	 */
	private int indexOfButton(JButton button)
	{
		for (int i = 0; i < listButton.length; i++)
		{
			if (button == listButton[i]) { return i; }
		}
		return -1;
	}

	/**
	 * This method will add your pressed key and your delay into listKeyAndName
	 * <p>
	 * The data is get from listObject
	 */
	private void addKeyToList()
	{
		listKeyAndDelay = new ArrayList<String[]>();
		for (int i = 0; i < listObject.size(); i++)
		{
			String keyName = listObject.get(i)[2].toString();
			String delay = listObject.get(i)[3].toString();
			String[] item = { keyName, delay };
			listKeyAndDelay.add(item);
		}

		robot.newListKey(listKeyAndDelay);
	}
}
